#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <termios.h>//串口
#include <sys/stat.h>
#include <fcntl.h>

#include <linux/input.h>

#include "sem.h"
#define SEND_OK 0xAA
#define N 32

typedef struct {
 	uint8_t head[3];	 //标识位st:
	uint8_t type;		 //数据类型
	uint8_t snum;		 //仓库编号

	uint8_t temp[2];	 //温度	
	uint8_t hum[2];		 //湿度
	uint8_t x;			 //三轴信息
	uint8_t y;			 
	uint8_t z;			 
	uint32_t ill;		 //光照
	uint32_t bet;		 //电池电量
	uint32_t adc; 		 //电位器信息
}MSG;
//高玉浩
typedef struct msg_queue{
    long type;
//	long msgtype;
	unsigned char text[N];
}M0;

typedef struct linklist{
	MSG data;
	struct linklist *next;
}linklist_t;

linklist_t *create_linklist(void)
{
	linklist_t *l = (linklist_t *)malloc(sizeof(linklist_t));
	l->next = NULL;
	return l;
}

int is_empty_linklist(linklist_t *l)
{
	return (l->next == NULL);
}

int insert_linklist(linklist_t *l,MSG x)
{
	linklist_t *node = (linklist_t *)malloc(sizeof(linklist_t));
	node->data = x;
	node->next = NULL;

	linklist_t *p = l;

	while(p->next != NULL)
	{
		p = p->next;
	}

	p->next = node;
//	node = p->next;

	return 1;
}


MSG msg;
MSG *pmsg;

int semid;
int msgid;
int dev_uart_fd, dev_led_fd2, dev_led_fd3, dev_buzzer_fd;//串口, LED2,LED3, 蜂鸣器
pthread_mutex_t lock0, lock1;
pthread_cond_t condition;

void serial_init(int fd)
{
    struct termios options;
    tcgetattr(fd, &options);
    options.c_cflag |= ( CLOCAL | CREAD );
    options.c_cflag &= ~CSIZE;
    options.c_cflag &= ~CRTSCTS;
    options.c_cflag |= CS8;
    options.c_cflag &= ~CSTOPB;
    options.c_iflag |= IGNPAR;
    options.c_iflag &= ~(ICRNL | IXON);
    options.c_oflag = 0;
    options.c_lflag = 0;

    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    tcsetattr(fd,TCSANOW,&options);
}

void *pthread_read_m0_func(void *arg)
{

//	puts("进入了读串口线程");
	
	while(1)
	{
	//	pthread_mutex_lock(&lock1);//上锁
//		pthread_cond_wait(&condition, &lock1);
//		pthread_mutex_lock(&lock0);//上锁
		read(dev_uart_fd, &msg, sizeof(MSG));
	
//		printf("%uF,%uF,%u%%,%u%%,%um/(s*s),%um/(s*s),%um/(s*s),%uLUX,%umV,%umV\n", msg.temp[0], msg.temp[1], msg.hum[0], msg.hum[1], msg.x, msg.y, msg.z, msg.ill, msg.bet, msg.adc);
//		pthread_mutex_unlock(&lock0);//解锁
//		pthread_mutex_unlock(&lock1);//解锁
	}
	return NULL;
}

void *pthread_shm_func(void *arg)
{
	while(1)
	{
		sem_p(semid, 0);
//		pthread_mutex_lock(&lock1);//上锁
//		pthread_mutex_lock(&lock0);//上锁
		*pmsg = msg;//读到共享内存
//		pthread_cond_signal(&condition);//唤醒pthread_cond_wait的阻塞，锁住lock1
//		pthread_mutex_unlock(&lock0);//解锁
		sem_v(semid, 0);
	}
}

void *pthread_linklist_func(void *arg)
{
	linklist_t *l = create_linklist();
//	pause();
	while(1)
	{
//		pthread_mutex_lock(&lock1);//上锁
//		pthread_mutex_lock(&lock0);//上锁
		insert_linklist(l, msg);
//		pthread_cond_signal(&condition);//唤醒pthread_cond_wait的阻塞，锁住lock1
//		pthread_mutex_unlock(&lock0);//解锁
	}
	
}


//高玉浩
void *pthread_uart_cmd_func(void *arg)
{
//	key_t key;
//	int msgid;
	M0 msg_buf;
	while(1)
	{
		msgrcv(msgid, &msg_buf, sizeof(msg_buf) - sizeof(long), 1L, 0);
		printf("recv:%x", msg_buf.text[0]);	
//		pthread_mutex_lock(&lock0);//上锁
		if(msg_buf.text[0] == 0x80)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);  //关闭风扇
		}

		if(msg_buf.text[0] == 0x81)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //一档
		}

		if(msg_buf.text[0] == 0x82)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //二档
		}

		if(msg_buf.text[0] == 0x83)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //三当
		}

		if(msg_buf.text[0] == 0x90)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //蜂鸣器关闭
		}
		if(msg_buf.text[0] == 0x91)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //打开
		}
		if(msg_buf.text[0] == 0x92)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //自动报警关闭
		}

		if(msg_buf.text[0] == 0x93)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //自动报警打开
		}


		if(msg_buf.text[0] == 0xa0)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //灯关


		}

		if(msg_buf.text[0] == 0xa1)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //灯开
		}


		if(msg_buf.text[0] == 0xbf)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //数码管关
		}



		if(msg_buf.text[0] == 0xb0)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //数码管0
		}
		if(msg_buf.text[0] == 0xb1)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //数码管0
		}
		if(msg_buf.text[0] == 0xb2)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //数码管0
		}
		if(msg_buf.text[0] == 0xb3)
		{
			write(dev_uart_fd, &msg_buf.text[0], 1);   //数码管0
		}
		
//		pthread_mutex_unlock(&lock0);//解锁
	}
}


void *pthread_A9_func(void *arg)
{
	M0 msg_buf;
	struct input_event event;
	char * buff = NULL;
	puts("jin ru le A9 xiancheng ,hai meijin si xun huan.");
	while(1)
	{
		msgrcv(msgid, &msg_buf, sizeof(msg_buf) - sizeof(long), 10L, 0);
		printf("recv:%d\n", msg_buf.text[0]);	

		if(msg_buf.text[0] == 0x10)
		{
			buff = "0";
			write(dev_led_fd2, buff, 1);   //灯关
		}

		if(msg_buf.text[0] == 0x11)
		{
			puts("kai led 1");
			buff = "1";
			write(dev_led_fd2, buff, 1);   //灯开
			puts("kai led 1 jieshu");
		}
		if(msg_buf.text[0] == 0x20)
		{
			buff = "0";
			write(dev_led_fd3, buff, 1);   //灯guan
		}
		if(msg_buf.text[0] == 0x22)
		{
			buff = "1";
			write(dev_led_fd3, buff, 1);   //灯开
		}
		
		if (msg_buf.text[0] == 1)
		{
			event.type = EV_SND;
			event.code = SND_TONE;
			event.value = 100;
			write(dev_buzzer_fd, &event, sizeof(struct input_event));
		}
		
		if (msg_buf.text[0] == 0)
		{
			event.type = EV_SND;
			event.code = SND_TONE;
			event.value = 0;
			write(dev_buzzer_fd, &event, sizeof(struct input_event));
		}

//		pthread_mutex_unlock(&lock0);//解锁
	}
}

int main (int argc, char *argv[])
{
	pthread_t pthread_read_m0, pthread_shm, pthread_linklist, pthread_uart_cmd, pthread_A9;

    int shmid;
	  
    key_t key;
    key = ftok("/", 'a');
    if (key < 0)
    {
        perror("fail to ftok");
        exit(-1);
    }
	fisrt_init_sem(&semid, &key);//初始化信号量
	init_sem(semid, 0, 1);
	
	pthread_mutex_init(&lock0, NULL);//初始化互斥锁
	pthread_mutex_init(&lock1, NULL);//初始化互斥锁
	pthread_cond_init(&condition, NULL);//初始化条件变量
	
    shmid = shmget(key, sizeof(MSG), IPC_CREAT | IPC_EXCL | 0777);
    if (shmid < 0)
    {
        if (errno = EEXIST)
        {
            shmid = shmget(key, 0, 0777);
        }
        else
        {
            perror("fail to shmget");
            exit(-1);
        }
    }
    
    if ((pmsg = (MSG *)shmat(shmid, NULL, 0)) == (MSG *)-1)//映射共享内存
    {
        perror("fail to shmat");
        exit(-1);
    }

	msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);//创建消息队列
	if(msgid == -1)
	{
		if(errno == EEXIST)
		{
			msgid = msgget(key, 0666);
		}
		else{
		perror("msgget");
		exit(1);
		}
	}
	
	if((dev_uart_fd = open ("/dev/ttyUSB0",O_RDWR)) < 0)//打开串口
	{
		perror("open uart err");
		return -1;
	}
	serial_init(dev_uart_fd);//初始化串口
	
#if 0
	if ((dev_led_fd = open ("/dev/led", O_RDWR)) < 0)//打开LED文件描述符号
	{
		printf ("Cann't open file /sys/class/leds/led2/brightness\n");
		exit (-1);
	}
#endif
	
	if ((dev_led_fd2 = open ("/sys/class/leds/led2/brightness", O_RDWR)) < 0)
	{
		printf ("Cann't open file /sys/class/leds/led2/brightness\n");
		exit (-1);
	}
	
	if ((dev_led_fd3 = open ("/sys/class/leds/led3/brightness", O_RDWR)) < 0)
	{
		printf ("Cann't open file /sys/class/leds/led2/brightness\n");
		exit (-1);
	}
	
	if ((dev_buzzer_fd = open ("/dev/event2", O_RDWR | O_NONBLOCK)) < 0)
	{
		printf ("Cann't open file /dev/beep\n");
		exit (-1);
	}
	printf ("pthread_led is ok\n");
	
	puts("映射共享内存完毕，准备创建线程");
	
	//*
	
	if(pthread_create(&pthread_read_m0, NULL, pthread_read_m0_func, NULL) != 0)
	{
		perror("fail to pthread_create");
		exit(1);
	}
	sleep(1);
	if(pthread_create(&pthread_shm, NULL, pthread_shm_func, NULL) != 0)
	{
		perror("fail to pthread_create");
		exit(1);
	}
	if(pthread_create(&pthread_linklist, NULL, pthread_linklist_func, NULL) != 0)
	{
		perror("fail to pthread_create");
		exit(1);
	}
		//高玉浩 M0线程
	if(pthread_create(&pthread_uart_cmd, NULL, pthread_uart_cmd_func, NULL) != 0)
	{
	    perror("fail to pthread_create");
		exit(-1);
	}
	//*/
	//A9设备led
	if(pthread_create(&pthread_A9, NULL, pthread_A9_func, NULL) != 0)
	{
	    perror("fail to pthread_create");
		exit(-1);
	}
	pause();

    return 0;
}
